#Test Flow 3: Configure LineRate, Coding and Amplitude Levels

        # Eye Mode
        EYEMODE  = pymlbertmgr.BERTMGR_SIGMODULATION.BERTMGR_PAM4
        # Tx Taps Mode
        TAPSMODE = pymlbertmgr.BERTMGR_TAPSMODE.BERTMGR_21TAPS
        # Line Rate (Gbaud)
        LINERATE = 106.25
        #FEC MODE
        FECMODE = pymlbertmgr.BERTMGR_FECMODE.BERTMGR_FECDISABLED
        #FEC PATTERN
        FECPATTERN = pymlbertmgr.BERTMGR_FECPATTERN.FECPATTERN_DISABLED
        # Creates PatternConfig initial struct
        TXPATTERN = pymlbertmgr.PatternConfig()
        # Tx Pattern
        TXPATTERN.pattern = pymlbertmgr.BERTMGR_PATTERNTYPE.BERTMGR_PRBS31
        # Tx Invertion
        TXPATTERN.invert = False
        # Creates PatternConfig initial struct
        RXPATTERN = pymlbertmgr.PatternConfig()
        # Rx pattern
        RXPATTERN.pattern = pymlbertmgr.BERTMGR_PATTERNTYPE.BERTMGR_PRBS31
        # Rx Inversion
        RXPATTERN.invert = False
       
        #Set Linerate
        SUCCESS =  mlbert.mlbertmgr_setLinerate(LINERATE, APPLYCONFIG)
        if SUCCESS != pymlbertmgr.BERTMGR_STATUS.BERTMGR_SUCCESS:
            raise Exception("Failed to set Linerate! : ", SUCCESS)
        print ("Linerate is set !")
        
        # set EyeMode
        SUCCESS =  mlbert.mlbertmgr_setEyeMode(EYEMODE, APPLYCONFIG)
        if SUCCESS != pymlbertmgr.BERTMGR_STATUS.BERTMGR_SUCCESS:
            raise Exception("Failed to set EyeMode! : ", SUCCESS)
        print ("EyeMode is set !")

        # Enable Gray Coding. Applied for PAM4 Eye Mode.
        #ENABLE = True
        #SUCCESS =  mlbert.mlbertmgr_setGrayCoding(ENABLE, APPLYCONFIG)
        #if SUCCESS != pymlbertmgr.BERTMGR_STATUS.BERTMGR_SUCCESS:
        #    raise Exception("Failed to set Gray Coding! : ", SUCCESS)
        #print ("Gray Coding is set !")
        

        # Set Taps Mode
        SUCCESS =  mlbert.mlbertmgr_setTapsMode(TAPSMODE, APPLYCONFIG)
        if SUCCESS != pymlbertmgr.BERTMGR_STATUS.BERTMGR_SUCCESS:
            raise Exception("Failed to set Taps Mode! : ", SUCCESS)
        print ("Taps Mode is set !")
        APPLYCONFIG = True    # Trigger the configuration of all the applied settings

        # Set FEC Mode. Check The table of features for compatibility
        SUCCESS =  mlbert.mlbertmgr_setFECMode(FECMODE, FECPATTERN, APPLYCONFIG)
        if SUCCESS != pymlbertmgr.BERTMGR_STATUS.BERTMGR_SUCCESS:
            raise Exception("Failed to set FEC Mode! : ", SUCCESS)
        print ("FEC Mode is set !")
        
        for channel in range(NB_CHANNELS):
            #Set Tx Pattern
            SUCCESS =  mlbert.mlbertmgr_setTxPattern(channel, TXPATTERN, APPLYCONFIG) 
            if SUCCESS != pymlbertmgr.BERTMGR_STATUS.BERTMGR_SUCCESS:
                raise Exception("Failed to set Tx Pattern! : ", SUCCESS)
            print ("Tx Patternset is set !")

            #Set Rx Pattern
            SUCCESS =  mlbert.mlbertmgr_setRxPattern(channel, RXPATTERN, APPLYCONFIG) 
            if SUCCESS != pymlbertmgr.BERTMGR_STATUS.BERTMGR_SUCCESS:
                raise Exception("Failed to set Rx Pattern! : ", SUCCESS)
            print ("Rx Pattern is set !")

           
##################################################################################################################################################
# Test Flow 4: Set advanced amplitude and equalization 

        # Edit parameters for your instance
        # Advanced Amplitude
        APROXAMPLITUDE = ctypes.pointer(ctypes.c_int(0))
        ADVANCEDAMPLITUDE = pymlbertmgr.AdvancedAmplitude()
        # Inner Eye level(500 to 1500). Applied for PAM4
        ADVANCEDAMPLITUDE.innerLevel = ctypes.c_int(1000)
        # Outer Eye level (1500 to 2500). Applied to PAM4
        ADVANCEDAMPLITUDE.outerLevel = ctypes.c_int(2000)
        # Scaling Level Percentage (70, 80, 90, 100, 110, 120)
        ADVANCEDAMPLITUDE.scalingLevel = ctypes.c_int(80)
        # 7-Taps Mode 
        for i in range(7):
            ADVANCEDAMPLITUDE.advancedTaps[i] = ctypes.c_int(0)     // tap5 should be 1000  
        
        for channel in range(NB_CHANNELS):# set advanced Amplitude on CHANNEL


            # Set Rx DSP MODE - optional
            #SUCCESS =  mlbert.mlbertmgr_setDSPMode(CHANNEL, DSPMODE, APPLYCONFIG)
            #if SUCCESS != pymlbertmgr.BERTMGR_STATUS.BERTMGR_SUCCESS:
            #    raise Exception("Failed to set DSP MODE! : ", SUCCESS)
            #print ("DSP MODE is set!")
        
            
            #Set Advanced Amplitude            
            SUCCESS =  mlbert.mlbertmgr_setAdvancedAmplitude(channel,
                                                         ADVANCEDAMPLITUDE,
                                                         APROXAMPLITUDE,
                                                         APPLYCONFIG)
            
            if SUCCESS != pymlbertmgr.BERTMGR_STATUS.BERTMGR_SUCCESS:
                raise Exception("Failed to set Advanced Amplitude! : ", SUCCESS)
            print("APROX AMPLITUDE = ", APROXAMPLITUDE[0])  

##################################################################################################################################################
 # Test Flow 5: Enable  disable Tx, Rx   
        for channel in range(NB_CHANNELS):
            # Edit parameters for your instance
            ISENABLED = ctypes.pointer(ctypes.c_bool(False))
            STATUS = True
            # Enable  Tx
            SUCCESS =  mlbert.mlbertmgr_TxEnable(channel, STATUS)
            if SUCCESS != pymlbertmgr.BERTMGR_STATUS.BERTMGR_SUCCESS:
                raise Exception("Failed to Enable Tx! :", SUCCESS)
            print ("Tx Enabled !")
            
                
            # Enable  Rx
            SUCCESS =  mlbert.mlbertmgr_RxEnable(channel, STATUS)
            if SUCCESS != pymlbertmgr.BERTMGR_STATUS.BERTMGR_SUCCESS:
                raise Exception( "Failed to Enable Rx! : ", SUCCESS)
            print ("Rx Enabled !")
               
            # Get Tx Status 
            SUCCESS =  mlbert.mlbertmgr_getTxStatus(channel, ISENABLED)
            if SUCCESS != pymlbertmgr.BERTMGR_STATUS.BERTMGR_SUCCESS:
                raise Exception("Failed to  Get Tx Status! : ", SUCCESS)
            print ("TX enable status : ", ISENABLED[0])
              
            # Get Rx Status 
            SUCCESS =  mlbert.mlbertmgr_getRxStatus(channel, ISENABLED)
            if SUCCESS != pymlbertmgr.BERTMGR_STATUS.BERTMGR_SUCCESS:
                raise Exception("Failed to  Get Rx Status! : ", SUCCESS)
            print ("RX enable status : " , ISENABLED[0])
       
##################################################################################################################################################
 # Test Flow 6: Get BERT active configuration settings 

        CONFIG = ctypes.pointer(pymlbertmgr.ConfigurationSettings())
        SUCCESS =  mlbert.mlbertmgr_getActiveConfig(CONFIG)
        if SUCCESS != pymlbertmgr.BERTMGR_STATUS.BERTMGR_SUCCESS:
            raise Exception("Failed to get configuration", pymlbertmgr.BERTMGR_STATUS(SUCCESS))
        print("Get Active Configuration Done!")
 
##################################################################################################################################################
#Test Flow 8: Execute fundamental BER test
        
        # Pre-allocate MEASBERDATA Struct
        MEASBERDATA = (pymlbertmgr.MeasurementsData*1024)()
        DATACOUNT = ctypes.pointer(ctypes.c_int(0))
        # Enable BER Data Accumulation. Otherwise, the latest Data is captured
        ACCUMULATE = False
        # BER Enbaled CHANNELS. First Channel is Enabled
        # If the test is under the fec feachure please check the  mlbertmgr_configureFECLinks for enabling link.
        BERENABLEDCH = 0b11111111
        VALUE = (ctypes.c_ushort*NB_CHANNELS)(0)
        # Before starting the BER accumulation, it is recommended to add a settling time of 2 seconds
        # ML4054B requires 5 seconds after the configuration
        # "pymlbertmgr.getConfigStatus()" will be implemented in a future library release to check the instrument configuration status and avoid adding a sleep time in the application script
        time.sleep(5)  #  For ML4079EN use 10 seconds
        # Initialize Rx Lock Status and Monitor Rx Lock Status
        SUCCESS = pymlbertmgr.BERTMGR_STATUS.BERTMGR_FAILED
        # Call Rx lock Status in a while loop
        RETRY = 20
        # initialize Rx Lock Monitor Flag
        SINGLEMONITORFLAG = pymlbertmgr.BERTMGR_MONITOR_FLAGS.BERTMGR_MONITOR_RXLOCK
            
        SUCCESS =  mlbert.mlbertmgr_enableMonitor(SINGLEMONITORFLAG)
        if SUCCESS != pymlbertmgr.BERTMGR_STATUS.BERTMGR_SUCCESS:
            raise Exception("Failed to  Enable Monitor! : ", SUCCESS)
        print ("Monitor Flags are Enabled!")
        # Wait for Monitor Data accumulation
        time.sleep(0.35)
        for channel in range(NB_CHANNELS):
            while (VALUE[channel] == 0 and RETRY > 0):
                time.sleep(0.1)    # Sleep for 100 ms
            # Single Read Monitor of Rx Lock Status
                SUCCESS = mlbert.mlbertmgr_singleReadMonitor(SINGLEMONITORFLAG, VALUE)
                if SUCCESS != pymlbertmgr.BERTMGR_STATUS.BERTMGR_SUCCESS:
                    raise Exception("Failed to Read single Monitor! : ", SUCCESS)
                RETRY -=1
            if VALUE[channel] == 1 :
                print("Rx ", channel, " is  locked!")
            else :
                print("Rx ", channel, " is not locked!")
                   
        # Disable Monitor Flags
        MONITORFLAGS = 0 
        SUCCESS =  mlbert.mlbertmgr_enableMonitor(MONITORFLAGS)
        if SUCCESS != pymlbertmgr.BERTMGR_STATUS.BERTMGR_SUCCESS:
            raise Exception("Failed to  Disable Monitor! : ", SUCCESS)
        print ("Monitor Flags are Disabled!")

        # Start BER. This function requires Rx Lock.
        mlbert.mlbertmgr_startBER(BERENABLEDCH, ACCUMULATE)
        # BER Counting Time
        # ML4054 BER Accumulation starts 4 seconds after enabling the BER process.
        #time.sleep(4) 
           
        #Get Available Data
        SUCCESS =  mlbert.mlbertmgr_getAvailableBERData(MEASBERDATA, DATACOUNT)    
        if SUCCESS != pymlbertmgr.BERTMGR_STATUS.BERTMGR_SUCCESS:
            raise Exception("Failed to Get Available Data!", SUCCESS)

        # print Out BER Data. Check MeasurementsData struct for more details
        print("Datacount: ", DATACOUNT[0])
        print("Measured BER Data : \r")
        for channel in range(NB_CHANNELS):
            #for ber if the fec is disabled
            print("\nchannel ", channel)
            print("\tEnabled Channels : ", MEASBERDATA[DATACOUNT[0] - 1].berData.enabledChannels[channel])
            print("\tLocked Channels : ", MEASBERDATA[DATACOUNT[0] - 1].berData.lockedChannels[channel])
            print("\tBER Capture Time : ", MEASBERDATA[DATACOUNT[0] - 1].berData.Time[channel])
            print("\tBit Count : ", MEASBERDATA[DATACOUNT[0] - 1].berData.BitCount[channel])     
            print("\tErrorCount_MSB: ", MEASBERDATA[DATACOUNT[0] - 1].berData.ErrorCount_MSB[channel])     
            print("\tErrorCount_LSB: ", MEASBERDATA[DATACOUNT[0] - 1].berData.ErrorCount_LSB[channel])     
            print("\tErrorCount : ", MEASBERDATA[DATACOUNT[0] - 1].berData.ErrorCount[channel])
            print("\tAccumulatedErrorCount_MSB: ", MEASBERDATA[DATACOUNT[0] - 1].berData.AccumulatedErrorCount_MSB[channel])
            print("\tBER_MSB_Interval: ", MEASBERDATA[DATACOUNT[0] - 1].berData.BER_MSB_Interval[channel])
            print("\tBER_MSB_Realtime: ", MEASBERDATA[DATACOUNT[0] - 1].berData.BER_MSB_Realtime[channel])
            print("\tAccumulatedErrorCount_LSB: ", MEASBERDATA[DATACOUNT[0] - 1].berData.AccumulatedErrorCount_LSB[channel])
            print("\tBER_LSB_Interval: ", MEASBERDATA[DATACOUNT[0] - 1].berData.BER_LSB_Interval[channel])
            print("\tBER_LSB_Realtime: ", MEASBERDATA[DATACOUNT[0] - 1].berData.AccumulatedErrorCount_LSB[channel])
            print("\tAccumulatedErrorCount  : ", MEASBERDATA[DATACOUNT[0] - 1].berData.AccumulatedErrorCount[channel])
            print("\tBER_Interval: ", MEASBERDATA[DATACOUNT[0] - 1].berData.BER_Interval[channel])
            print("\tBER Realtime : ", MEASBERDATA[DATACOUNT[0] - 1].berData.BER_Realtime[channel])
        #Stop BER 
        SUCCESS =  mlbert.mlbertmgr_stopBER()
        if SUCCESS != pymlbertmgr.BERTMGR_STATUS.BERTMGR_SUCCESS:
            raise Exception("Failed to Stop BER Test!", SUCCESS)
        print ("BER Test stopped!")
        
        